home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
tpbind.zip
/
BIND.DOC
< prev
next >
Wrap
Text File
|
1991-05-22
|
12KB
|
437 lines
Dear Turbo Pascal 6.0/Windows programmer,
Thank you for downloading the Loose Data Binder! The
Binder combines concepts from FlexList, OOP's generic
container objects, and Borland's TurboVision/ObjectWindows
TCollection object.
Adaptability
============
Think of the Loose Data Binder as a loose-leaf notebook.
You can insert data into the LDB just like inserting pages
into a notebook. And of course you can just as easily take
the data back out. You can access the LDB as if it were a
combination stack-queue-deque-list-array. You can arrange
your data in any order and even specify a compare function
for sorting and/or searching. The LDB expands or contracts
automatically to accommodate varying numbers of nodes. The
CopyBinder, derived from Binder (LDB), gives the LDB the
ability to clone the data you want stored in a LDB on the
fly. It can also copy the data to/from the LDB nodes and
your variables. Since a LDB is initialized at run time,
the data it holds or even its creation can be specified at
run time, thus allowing your applications new dimensions of
adaptability to user inputs.
Getting Started
===============
Copy bind.pas to your compiler's standard source directory.
Now for an example. The compile and run LDB1.PAS. Its
contents are listed below. It builds a LDB of cloned nodes
and then displays them in several different ways.
program ldb1;
uses bind;
type strPtr = ^string;
procedure display(D, M, A : pointer); far;
type strPtr = ^string;
intPtr = ^integer;
var i : integer;
begin
i := length(strPtr(D)^);
inc(intPtr(A)^,i);
writeln('length: ',i,
' accumulated: ',intPtr(A)^,
' string: ',strPtr(D)^);
end;
function strcmp(D1, D2 : pointer) : integer; far;
begin
if (strPtr(D1)^ < strPtr(D2)^) then
strcmp := -1
else if (strPtr(D1)^ > strPtr(D2)^) then
strcmp := 1
else
strcmp := 0
end;
const
s1 : string = 'Now is the time';
s2 : string = 'for all programmers';
s3 : string = 'to stop reinventing';
s4 : string = 'the linked list!';
var B : CopyBinder;
i : word;
begin
B.Init(CSTRING);
B.pushC(@s1);
B.insqC(@s2);
B.atInsC(B.getNodes,@s3);
B.insqC(@s4);
while (B.next) do
writeln(strPtr(B.current)^);
writeln;
for i := 0 to (B.getNodes - 1) do
writeln(strPtr(B.atGet(i))^);
writeln;
i := 0;
B.forEach(display,nil,@i);
writeln;
B.setCompare(strcmp);
B.sort;
i := 0;
B.forEach(display,nil,@i);
B.Done;
readln
end.
Notice that first the LDB is pushed like a stack. Next it
is queued, arrayed, and finally queued. Next is used to
walk across the binder. Notice that stack, queue, and
array primitives don't disturb the current node!
The LDB also has built in iterators, much more powerful than
TurboVision's TCollection. The forEach iterator applies the
given function against each element of the LDB and passes in
what can be used as a mask and an accumulator. I'm using
the accumulator to sum the length of strings printed thus
far.
Next a compare function is specified for the LDB and a sort
is performed.
The CopyBinder destructor calls Dfree() for each element
when discarding the instance. Please note that the Binder
destructor does not, by default, which allows it to bind
data variables in your program. If you use the CopyBinder
to bind non allocated data, besure to override its
destructor so that it doesn't try to delete non-dynamic
data!
Our next example can be found in ldb2.cpp.
program ldb2;
uses bind;
type strPtr = ^string;
const
s1 : string = 'Now is the time';
s2 : string = 'for all programmers';
s3 : string = 'to stop reinventing';
s4 : string = 'the linked list';
s5 : string = 'and container classes.';
function strcmp(D1, D2 : pointer) : integer; far;
begin
if (strPtr(D1)^ < strPtr(D2)^) then
strcmp := -1
else if (strPtr(D1)^ > strPtr(D2)^) then
strcmp := 1
else
strcmp := 0
end;
var B : Binder;
i : word;
begin
B.Init;
B.setDelta(1);
B.setLimit(3);
B.setMaxNodes(3);
B.push(@s1);
B.insq(@s2);
B.atIns(B.getNodes,@s3);
B.insq(@s4);
B.insq(@s5);
while (B.next) do
writeln(strPtr(B.current)^);
B.setComparE(strcmp);
if (B.findFirst(@s3) <> BNOTFOUND) then
writeln(strPtr(B.current)^);
B.Done;
readln
end.
I've used the Binder class here, which only binds pointers
to data. The constructor is called, and then the LDB is
restricted to having a maximum of three nodes. The
following relationship is always maintained in a LDB:
1 <= delta <= limit <= maxNodes <= BMAXNODES
The last two fail which cause them to call the binder
error function explaining there are no vacancies left.
Next the compare function is set and a search is performed.
The LDB knows automatically that it isn't sorted so the
search is a linear one. If it had been sorted than a
binary search would have been used internally. FindFirst
set the current node and returns its index.
Remember the Binder destructor, by default, doesn't delete
its member elements.
For our last example, let's revisit the CopyBinder class.
I didn't tell you before, but CopyBinder has two virtual
functions, Dclone() and Dcopy(), that tells its other
member functions how to clone and copy your data in the
course of operations. CSTRING is defined as 0, which tells
these functions to treat the data as normal C strings.
When cloning the data, the clone was only made as big as
necessary to hold the string being warehoused. If you
give it another value, other than 0, then cloning and
copying will be performed for data of this fixed size.
If you have variant data, other than strings, or data with
suballocated memory, than you can override these functions
to handle your data accordingly. Besure to override Dfree()
as appropriate. For this example, though, we'll use fixed
sized data.
The following listing can be found in ldb3.cpp.
program ldb3;
uses bind;
type
YourRecPtr = ^YourRec;
YourRec = record
name : ^string;
end;
procedure display(D, M, A : pointer); far;
begin
writeln(YourRecPtr(D)^.name^)
end;
const
s : string = 'Pat Programmer';
var
B : CopyBinder;
R : YourRec;
i : word;
begin
B.Init(sizeof(YourRec));
R.name := @s;
for i := 1 to 10 do
B.ins(@R);
B.forEach(display,nil,nil);
B.allDel;
B.Done;
readln
end.
Here the CopyBinder is constructed to clone and copy data
that is sizeof(YourRec) bytes long. As it turns out though,
I don't call any cloning functions (they end in capital C
for Clone/Copy). Since CopyBinder is derived publicly from
the Binder object the latter's functions are still available.
The forEach iterator is used to display the elements.
Notice that B.allDel is called to discard all elements of
the binder without disposing them before the destructor can
get at them to dispose them. Deleting nonallocated memory
can be pretty serious business. Don't do it!
This program brings up another point though. It has simply
inserted five pointers to the same record. Even if I
had called B.insC() instead there would have been five
copies containing five pointers to the same name string:
"Pat Programmer". You must be sure to resolve double
ownership problems. Please note that if B.insC() had been
called instead of calling B.ins() then B.allDel would
have discarded the pointers to these five clones without
disposing them! Since Dfree(), Dclone(), Dcopy() are virtual,
your can resolve any complexities inherent in your data
types by overriding these functions.
Diving In
=========
I've tried to give you a flavor for the LDB and keep the
download file to a reasonable length. Since you have the
source code, study it, it's not too long. And use the
bind.pas interface section as a quite reference guide.
Small Code Sizes, Less Testing
==============================
Your applications can now have as many stacks, queues,
deques, lists, and/or elastic arrays without code size
explosion. That's because the LDB operates on any type of
data, so new objects needn't be derived to accommodate new
data types. Laborious testing of a myriad of linked list
primitives, especially for boundary condition faults, is
thus avoided.
Coherent Flexible Design - Lower Investment
===========================================
It's no problem modifying your applications in midstream to
incorporate various and differing list types, with the LDB
no linked list code needs to be scrapped or rewritten.
Investment in non reusable linked list code is essentially
eliminated. And with uniformity across applications and
between Turbo Pascal and Turbo/Borland C++ versions, your
software maintenance costs can be greatly reduced.
Less, Less, Less ...
====================
When you use LDB's for all your linked list needs, your
applications will require:
* less documentation
* less testing
* less code space
* less programming time
* less investment in non reusable code
* less software maintenance effort
* less cross application training
Get Popping - Register Today!
=============================
Register bind.pas today and get your applications popping!
This version of bind.pas is shareware meaning try before you
buy. It is provided for your convenience in evaluating the
product to reach a buy/no buy decision. For any other use
you are required, by law, to register. Registration,
provides you with a license to use bind.pas and its
associated files in your applications without royality.
TP Loose Leaf Binder registration fee ... $15
Upon registration, you will be sent a DOS formatted diskette
with the next version of the LDB tool, when available.
Please specify 3.5" or 5.25" diskette and the date of your
current version! If I receive 100 or more registrations,
I will write a full length manual and put a ready to print
copy on diskette. Registrants are entitled to telephone
support.
Make your check or money order payable to:
PSW / Power SoftWare
P.O. Box 10072
McLean, VA 22102 - 8072
USA (703) 759-3838
Additional Versions
===================
Depending on demand, a version will be introduced for ANSI C.
Please feel free to contact me with your comments or
suggestions. If you call, please don't call in the middle of
the night or on Sundays!
Background
==========
I had a need to port FlexList to Microsoft Windows and other
"after-thought" virtual memory systems and also to expand it
into what I call a PolyMesh, polymorphic nodes belonging to
more than one FlexList at the same time.
What you have downloaded here is a TP version incorporating
the functionality of TCollect married to the functionality
of FlexList. The binder is not streamable here. That code
I extracted since most won't need it until their programs
grow much more complex.
Thanks again! John